package com.codeyang.mocktest2.mockit;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import static org.mockito.Mockito.mock;

/**
 * 描述: describe
 *
 * @author shengyang5
 * @version 2021/7/22 11:51
 */
@RunWith(MockitoJUnitRunner.class)
public class MockitStudy01 {


    /**
     * 1 验证行为是否发生
     *
     * @throws Exception
     */
    @Test
    public void test() throws Exception {
        //模拟创建一个List对象
        List<Integer> mock = mock(List.class);
        //调用mock对象的方法
        mock.add(1);
        mock.clear();
        //验证方法是否执行
        Mockito.verify(mock).add(1);
        Mockito.verify(mock).clear();

    }

    /**
     * 2 多次触发返回不同值
     */
    @Test
    public void test2() throws Exception {
        //mock一个Iterator类
        Iterator mock = mock(Iterator.class);
        //预设当iterator调用next()时第一次返回hello，第n次都返回world
        //Mockito.when(methodCall).thenReturn(value1).thenReturn(value2)	触发时第一次返回value1，第n次都返回value2
        Mockito.when(mock.next()).thenReturn("hello").thenReturn("world");
        //使用mock的对象
        String result = mock.next() + " " + mock.next() + " " + mock.next();
        //验证结果
        Assert.assertEquals("hello world world", result);
    }

    /**
     *  3模拟抛出异常
     */

    @Test(expected = IOException.class)//期望报IO异常
    public void when_thenThrow() throws IOException {
        OutputStream mock = Mockito.mock(OutputStream.class);
        //预设当流关闭时抛出异常
        Mockito.doThrow(new IOException()).when(mock).close();
        mock.close();
    }

    /**
     * 4 使用默认Answer模拟对象
     * RETURNS_DEEP_STUBS 是创建mock对象时的备选参数之一
     * 以下方法deepstubsTest和deepstubsTest2是等价的
     */
    @Test
    public void deepstubsTest() {
        A a = Mockito.mock(A.class, Mockito.RETURNS_DEEP_STUBS);
        Mockito.when(a.getB().getName()).thenReturn("Beijing");
        Assert.assertEquals("Beijing", a.getB().getName());
    }

    @Test
    public void deepstubsTest2() {
        A a = Mockito.mock(A.class);
        B b = Mockito.mock(B.class);
        System.out.println(b);
        Mockito.when(a.getB()).thenReturn(b);
        Mockito.when(b.getName()).thenReturn("Beijing");
        Assert.assertEquals("Beijing", a.getB().getName());
    }

    class A {
        private B b;

        public B getB() {
            return b;
        }

        public void setB(B b) {
            this.b = b;
        }
    }

    class B {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getSex(Integer sex) {
            if (sex == 1) {
                return "man";
            } else {
                return "woman";
            }
        }
    }

    /**
     * 5 参数匹配
     */
    @Test
    public void with_arguments() {
        B b = Mockito.mock(B.class);
        //预设根据不同的参数返回不同的结果
        Mockito.when(b.getSex(1)).thenReturn("男");
        Mockito.when(b.getSex(2)).thenReturn("女");
        Assert.assertEquals("男", b.getSex(1));
        Assert.assertEquals("女", b.getSex(2));
        //对于没有预设的情况会返回默认值
        Assert.assertEquals(null, b.getSex(0));
    }


}
